﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FastColoredTextBoxNS;
using System.Text.RegularExpressions;

namespace V32VM
{
    public partial class DisassemblerViewForm : Form, IMemoryUpdatable
    {
        private const int MAX_DISASSEMBLY_LINES = 1000;

        public Source MemoryStartAddrSource { get; private set; }

        public DisassemblerViewForm(Source source)
        {
            InitializeComponent();

            MemoryStartAddrSource = source;
            UpdateMemory();
        }

        private void updateText()
        {
            this.Text = "Disassembly View: " + MemoryStartAddrSource.ToString() + (MemoryStartAddrSource is ConstantSource ? "" : " = " + MemoryStartAddrSource.GetValue());
        }

        public void UpdateMemory()
        {
            updateText();
            disassemblyTextBox.Text = string.Join(Environment.NewLine,
                from line in
                    new Disassembler(Program.VM.memory)
                    .dissasemble(MemoryStartAddrSource.GetValue(), MAX_DISASSEMBLY_LINES)
                select string.Format(" {0:0000000000}  {1}", line.Item1, line.Item2));
            disassemblyTextBox.Selection = new Range(disassemblyTextBox, new Place(), new Place());
        }

        private void editToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SourceEditDialog sourceEdit = new SourceEditDialog(MemoryStartAddrSource);
            if (sourceEdit.ShowDialog(this) == DialogResult.OK)
            {
                this.MemoryStartAddrSource = sourceEdit.Source;
                UpdateMemory();
            }
        }
        private void flattenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.MemoryStartAddrSource = this.MemoryStartAddrSource.Flatten();
            updateText();
        }

        #region Assembly Coloring
        TextStyle lineNumberStyle = new TextStyle(Brushes.Teal, null, FontStyle.Regular);
        TextStyle opcodeStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular);
        TextStyle registerStyle = new TextStyle(Brushes.Green, null, FontStyle.Regular);
        TextStyle numberStyle = new TextStyle(Brushes.DarkBlue, null, FontStyle.Regular);
        TextStyle operatorStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular);

        private void disassemblyTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

            string numberRegex = @"[0-9]+";
            string opcodeRegex = @"LD|ADD|SUB|MUL|DIV|MOD|AND|OR|XOR|LSH|RSH|INV|NEG|CLR|CMP|JMP|JE|JNE|JG|JL|JLE|JGE|INT|IRET|\.DATA|\.DATABLOCK";
            string registerRegex = @"\b(A|B|C|D|E|F|G|T|U|V|W|X|Y|Z|S|IP|SP|FL)\b";
            string operatorRegex = @"\[|\]|\+|-";

            e.ChangedRange.ClearStyle(lineNumberStyle, opcodeStyle, registerStyle, numberStyle, operatorStyle);

            //for (int i = 0; i < disassemblyTextBox.LinesCount; i++)
            //    foreach (Match match in Regex.Matches(disassemblyTextBox.Lines[i], numberRegex))
            //        new Range(disassemblyTextBox, match.Index, i, match.Index + match.Length, i)
            //            .SetStyle(match.Index == 1 ? lineNumberStyle : numberStyle);
            e.ChangedRange.SetStyle(lineNumberStyle, numberRegex);

            e.ChangedRange.SetStyle(operatorStyle, operatorRegex);
            e.ChangedRange.SetStyle(registerStyle, registerRegex, RegexOptions.IgnoreCase);
            e.ChangedRange.SetStyle(opcodeStyle, opcodeRegex, RegexOptions.IgnoreCase);
        }
        #endregion

        private void DisassemblerViewForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            MainForm.ViewForms.Remove(this);
        }
    }
}
